﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Resources;
using System.Data.SqlClient;
using System.Xml;
using System.IO;

using XEvents.Library;
using XEvents.Library.Targets;

namespace ExtendedEventsManager
{
    public partial class EventSessionForm : Form
    {
        private SqlServer server;

        public SqlServer Server
        {
            get { return server; }
        }

        public EventSessionForm(SqlServer si)
        {
            InitializeComponent();
            server = si;
            this.Text = "Extended Events Session Manager (" + server.ServerName + ")";
            this.textBox1.Text = server.ServerName;
        }

        private void BindTreeView()
        {
            XmlDocument xdoc = server.GetSessionXml();
            System.Diagnostics.Debug.WriteLine(xdoc.InnerXml);

            treeView1.Nodes.Clear();
            treeView1.Nodes.Add(new XEventTreeNode(server.ServerName, xdoc.DocumentElement));
            TreeNode tNode = new TreeNode();
            tNode = treeView1.Nodes[0];

            // SECTION 3. Populate the TreeView with the DOM nodes.
            AddNode(xdoc.DocumentElement, tNode);
            //treeView1.ExpandAll();
        }

        private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
        {
            XmlNode xNode;
            TreeNode tNode;
            XmlNodeList nodeList;
            int i;

            // Loop through the XML nodes until the leaf is reached.
            // Add the nodes to the TreeView during the looping process.
            if (inXmlNode.HasChildNodes)
            {
                nodeList = inXmlNode.ChildNodes;
                for (i = 0; i <= nodeList.Count - 1; i++)
                {
                    xNode = inXmlNode.ChildNodes[i];
                    if (xNode.Attributes == null)
                        inTreeNode.Nodes.Add(new XEventTreeNode(xNode.Name, xNode));
                    else if (xNode.Attributes["Name"] == null)
                        inTreeNode.Nodes.Add(new XEventTreeNode(xNode.Name, xNode));
                    else
                    {
                        XEventTreeNode xetn = new XEventTreeNode(xNode.Attributes["Name"].Value, xNode);
                        inTreeNode.Nodes.Add(xetn);
                    }
                    tNode = inTreeNode.Nodes[i];
                    AddNode(xNode, tNode);
                }
            }
            else
            {

                // Here you need to pull the data from the XmlNode based on the
                // type of node, whether attribute values are required, and so forth.

                if (inXmlNode.Attributes == null || inXmlNode.Attributes["Name"] == null)
                    inTreeNode.Text = inXmlNode.Name;
                else
                {
                    inTreeNode.Text = inXmlNode.Attributes["Name"].Value;
                }
            }

        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode tNode = e.Node;
            XmlNode xnode = (XmlNode)tNode.Tag;

            string nodeInfo = string.Empty;

            if (xnode != null)
            {
                if (xnode.ParentNode.Name == "Value")
                {
                    nodeInfo = xnode.Value;
                }
                else
                {
                    foreach (XmlAttribute xa in xnode.Attributes)
                    {
                        nodeInfo += xa.Name + ": " + xa.Value + "\r\n";
                    }
                }
                textBox2.Text = nodeInfo;
            }
        }

        private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            treeView1.SelectedNode = e.Node;
            XmlNode xNode = (XmlNode)e.Node.Tag;
            if (e.Button == MouseButtons.Right)
            {
                if (e.Node.Level == 0)
                {
                    GenerateServerMenu();
                    contextMenuStrip1.Show(treeView1, e.Location);
                }
                else if (xNode.Name == "EventSession")
                {
                    GenerateSessionMenu(xNode);
                    contextMenuStrip1.Show(treeView1, e.Location);
                }
                else if (xNode.Name == "EventSessionTarget")
                {
                    contextMenuStrip1.Items.Clear();
                    ToolStripMenuItem tsmi;

                    tsmi = new ToolStripMenuItem("View Target Data");
                    tsmi.Click += new EventHandler(ViewTargetData_Click);
                    tsmi.Enabled = (xNode.ParentNode.ParentNode.Attributes["SessionState"].Value == "Start");

                    contextMenuStrip1.Items.Add(tsmi);
                    contextMenuStrip1.Show(treeView1, e.Location);
                }
            }
        }

        private void WriteTextToFile(string text)
        {
            SaveFileDialog sfd = new SaveFileDialog();

            saveFileDialog.AddExtension = true;
            saveFileDialog.DefaultExt = ".sql";

            DialogResult dr = saveFileDialog.ShowDialog();
            if (dr != DialogResult.Cancel && saveFileDialog.FileName != null && saveFileDialog.FileName != string.Empty)
            {
                System.IO.Stream s = saveFileDialog.OpenFile();
                StreamWriter sw = new StreamWriter(s);
                sw.Write(text);
                sw.Flush();
                s.Flush();
                sw.Close();
                s.Close();
            }
        }

        private void GenerateServerMenu()
        {
            contextMenuStrip1.Items.Clear();
            ToolStripMenuItem tsmi = new ToolStripMenuItem("New Event Session");
            tsmi.Click += new EventHandler(NewEventSession_Click);
            contextMenuStrip1.Items.Add(tsmi);

            contextMenuStrip1.Items.Add(new ToolStripSeparator());

            tsmi = new ToolStripMenuItem("Refresh");
            tsmi.Click += new EventHandler(Refresh_Click);
            contextMenuStrip1.Items.Add(tsmi);

            contextMenuStrip1.Items.Add(new ToolStripSeparator());

            tsmi = new ToolStripMenuItem("View XEvent Metadata");
            tsmi.Click +=new EventHandler(ViewMetadata_Click);
            contextMenuStrip1.Items.Add(tsmi);
        }

        private void GenerateSessionMenu(XmlNode xNode)
        {
            contextMenuStrip1.Items.Clear();
            ToolStripMenuItem tsmi;
            ToolStripMenuItem subtsmi;

            tsmi = new ToolStripMenuItem("Edit Event Session");
            tsmi.Click += new EventHandler(EditEventSession_Click);
            contextMenuStrip1.Items.Add(tsmi);

            contextMenuStrip1.Items.Add(new ToolStripSeparator());
            
            tsmi = new ToolStripMenuItem("Drop Event Session");
            tsmi.Click += new EventHandler(DropEventSession_Click);
            contextMenuStrip1.Items.Add(tsmi);

            contextMenuStrip1.Items.Add(new ToolStripSeparator());

            tsmi = new ToolStripMenuItem("Script Session as");
            
            subtsmi = new ToolStripMenuItem("CREATE to");
            subtsmi.DropDownItems.Add(new ToolStripMenuItem("File", null, new EventHandler(ScriptToFile_Click)));
            subtsmi.DropDownItems.Add(new ToolStripMenuItem("Clipboard", null, new EventHandler(ScriptToClipboard_Click)));
            tsmi.DropDownItems.Add(subtsmi);

            subtsmi = new ToolStripMenuItem("DROP to");
            subtsmi.DropDownItems.Add(new ToolStripMenuItem("File", null, new EventHandler(ScriptToFile_Click)));
            subtsmi.DropDownItems.Add(new ToolStripMenuItem("Clipboard", null, new EventHandler(ScriptToClipboard_Click)));
            tsmi.DropDownItems.Add(subtsmi);


            contextMenuStrip1.Items.Add(tsmi);
            contextMenuStrip1.Items.Add(new ToolStripSeparator());
            
            tsmi = new ToolStripMenuItem("Start Event Session");
            tsmi.Click += new EventHandler(StartEventSession_Click);
            if (xNode.Attributes["current_state"] != null)
            {
                    tsmi.Enabled = !(xNode.Attributes["current_state"].Value == "Started");
            }
            contextMenuStrip1.Items.Add(tsmi);
            
            tsmi = new ToolStripMenuItem("Stop Event Session");
            tsmi.Click += new EventHandler(StopEventSession_Click);
            if (xNode.Attributes["current_state"] != null)
            {
                tsmi.Enabled = (xNode.Attributes["current_state"].Value == "Started");
            }
            contextMenuStrip1.Items.Add(tsmi);

        }

        #region Session Events

        private void ChangeSessionState(EventSession session, SessionState State)
        {
            try
            {
                session.ChangeSessionState(State);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "An Error Occured!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            Load_Form();
        }

        private void DropEventSession(EventSession ses)
        {
            try
            {
                ses.DropEventSession();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "An Error Occured!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            Load_Form();
        }

        #endregion

        #region Menu Click Events

        void ViewTargetData_Click(object sender, EventArgs e)
        {
            TargetData td = this.SelectedTarget.TargetData;
            TelerikTest tt = new TelerikTest();
            switch (this.SelectedTarget.Name.Split('.').ElementAt(1))
            {
                case "ring_buffer":
                    tt = new TelerikTest((Target_RingBuffer)td);
                    RingBufferDataViewer rbdv = new RingBufferDataViewer((Target_RingBuffer)td);
                    rbdv.MdiParent = this.MdiParent;
                    rbdv.Text = this.SelectedTarget.Parent.Name + " " + this.SelectedTarget.Name + " Data";
                    rbdv.Show();
                    break;
                case "asynchronous_file_target":
                    FileDataViewer fdv = new FileDataViewer((Target_File)td);
                    fdv.MdiParent = this.MdiParent;
                    fdv.Text = this.SelectedTarget.Parent.Name + " " + this.SelectedTarget.Name + " Data";
                    fdv.Show();
                    break;
                case "pair_matching":
                    tt = new TelerikTest((Target_PairMatching)td);
                    break;
                case "synchronous_event_counter":
                    tt = new TelerikTest((Target_Counter)td);
                    break;
            }
            tt.MdiParent = this.MdiParent;
            tt.Show();
        }
        void StartEventSession_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Are you sure you want to start collection for the " + this.SelectedSession.Name + " session?", "Start Session Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes)
            {
                ChangeSessionState(this.SelectedSession, SessionState.Start);
            }
        }
        void StopEventSession_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("Are you sure you want to stop collection for the " + this.SelectedSession.Name + " session?", "Stop Session Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (dr == DialogResult.Yes)
            {
                ChangeSessionState(this.SelectedSession, SessionState.Stop);
            }
        }

        void ScriptToFile_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
            switch (tsmi.OwnerItem.Text)
            {
                case "CREATE to":
                    WriteTextToFile(this.SelectedSession.GenerateSQLScript());
                    break;
                case "DROP to":
                    WriteTextToFile(this.SelectedSession.GenerateDropScript());
                    break;
            }
        }

        void ScriptToClipboard_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
            switch (tsmi.OwnerItem.Text)
            {
                case "CREATE to":
                    Clipboard.SetText(this.SelectedSession.GenerateSQLScript());
                    break;
                case "DROP to":
                    Clipboard.SetText(this.SelectedSession.GenerateDropScript());
                    break;
            } 
        }

        void EditEventSession_Click(object sender, EventArgs e)
        {
            SessionEditorForm editor = new SessionEditorForm(this.SelectedSession, this);
            editor.MdiParent = this.MdiParent;
            editor.Show();
        }

        private EventSession SelectedSession
        {
            get
            {
                TreeNode tn = treeView1.SelectedNode;
                return server.EventSessions[tn.Text];
            }
        }

        private EventSessionTarget SelectedTarget
        {
            get
            {
                TreeNode tn = treeView1.SelectedNode;
                TreeNode pn = treeView1.SelectedNode.Parent.Parent;
                return server.EventSessions[pn.Text].Targets[tn.Text];
            }
        }

        void DropEventSession_Click(object sender, EventArgs e)
        {
            DropEventSession(this.SelectedSession);
        }

        void NewEventSession_Click(object sender, EventArgs e)
        {
            EventSession ses = new EventSession(server);
            SessionEditorForm editor = new SessionEditorForm(ses, this);
            editor.MdiParent = this.MdiParent;
            editor.Show();
        }

        void Refresh_Click(object sender, EventArgs e)
        {
            Load_Form();
        }

        void ViewMetadata_Click(object sender, EventArgs e)
        {
            MetaDataViewerForm m = new MetaDataViewerForm(server);
            m.MdiParent = this.MdiParent;
            m.Show();
            m.Text = "Extended Events Meta Data Viewer (" + this.textBox1.Text + ")";
        }

        #endregion

        public void Load_Form()
        {
            server.Refresh();
            BindTreeView();
            treeView1.Nodes[0].Expand();

        }

        private void EventSession_Load(object sender, EventArgs e)
        {
            Load_Form();
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Clipboard.SetText(this.textBox2.Text);
        }
    }
}
